package LABS.lab2;

/**************************************************************
* Class KWArrayList
* @author Jeff Thomas
* @vesion 1.0.0
* Date: 02.05.2008
* Copyright 2008, Jeff Thomas
***************************************************************/

/** This class implements some of the methods of the Java
*   ArrayList class.
*   @author Koffman & Wolfgang
*/

public class KWArrayList < E > {
  // Data Fields
  /** The default initial capacity */
  private static final int INITIAL_CAPACITY = 10;

  /** The underlying data array */
  private E[] theData;

  /** The current size */
  private int size = 0;

  /** The current capacity */
  private int capacity = 0;
/**************************************************************
* Main
* Task:	1. Create driver for KWArrayList class
*			2. Test data
* Side Effects: None
***************************************************************/  
  	public static void main(String[] args)
  	{
  		KWArrayList<Comparable> a = new KWArrayList<Comparable>(8);
		a.add(10.0);
		a.add(13.2);
		a.add(15.7);
		a.add(14.7);
		a.add(1.6);
		testCapacity(a);
		testFind(a);
		System.out.println();
		KWArrayList<Comparable> b = new KWArrayList<Comparable>(5);
		b.add("Hello");
		b.add("Goodbye");
		b.add("Jeff");
		testCapacity(b);
		testFind(b);
  	}
/**************************************************************
* testCapacity
* @param a - KWArrrayList of type E
* Task:	1. Test capacity and size of ArrayList
* Side Effects: None
***************************************************************/	
	public static void testCapacity(KWArrayList a)
	{
		System.out.println("Capacity: " + a.capacity);
		System.out.println("Size: " + a.size());
	}
/**************************************************************
* testFind
* @param a - KWArrayList of type E
* Task:	1. Test the find method 
* Side Effects: None
***************************************************************/	
	public static void testFind(KWArrayList a)
	{
		findResult(a.find(1.6));
		findResult(a.find(2.0));
		findResult(a.find("Jeff"));
		findResult(a.find("jeff"));
	}
/**************************************************************
* Find Result
* @param f - int from result of find method
* Task:	1. determine result of find method
* Side Effects: None
***************************************************************/	
	public static void findResult(int f)
	{
		if (f == -1)
			System.out.println("Not found");
		else
			System.out.println("Found");
	}
  
/**************************************************************
* KWArrayList(int)
* @param c - integer of capacity
* Task:	1. Construct KWArrayList with given capacity
* Side Effects: None
***************************************************************/
	public KWArrayList(int c) 
	{
		capacity = c;
		theData = (E[])new Object[capacity];
	}
	
/**************************************************************
* Find
* @param search - Generic type E to search for
* @return - index if found in array or -1 if not found
* Task:	1. Search the arraylist for giving parameter
* Side Effects: None
***************************************************************/
	public int find(E search)
	{
		if (search == null)
				return -1;
		for (int i = 0; i <= size; i++)
		{
			if (theData[i] == null)
				return -1;
			else if (theData[i].getClass() != search.getClass())
				return -1;
			else if (theData[i].equals(search))
				return i;
		}
		return -1;
	}
  /** Construct an empty KWArrayList with the default
        initial capacity
   */
  public KWArrayList() {
    capacity = INITIAL_CAPACITY;
    theData = (E[])new Object[capacity];
  }

  /** Add an entry to the data inserting it after the
        last item in the array.
        @param theValue - The value to be inserted
  */
  public boolean add(E anEntry) {
    if (size == capacity) {
      reallocate();
    }
    theData[size] = anEntry;
    size++;
    return true;
  }

  /** Add an entry to the data inserting it before the
        item at the specified index.
        @param index - The index of the value that the new
        value is to be inserted in front of.
        @param anEntry - The value to be inserted
        @throws ArrayIndexOUtOfBoundsException if index is
        less than zero or greater than size
  */
  public void add(int index, E anEntry) {
	if (index < 0 || index >= size) {
      throw new ArrayIndexOutOfBoundsException(index);
    }
    if (size == capacity) {
      reallocate();
    }
    // Shift data in elements from index to size - 1
	 for (int i = size; i > index; i--) {
	   theData[i] = theData[i -1];
	 }
	 // Insert the new item.
	 theData[index] = anEntry;
	 size++;
  }

  /** Get a value in the array based on its index.
        @param index - The index of the item desired
        @return The contents of the array at that index
        @throws ArrayIndexOutOfBoundsException - if the index
        is negative or if it is greater than or equal to the
        current size
   */
  public E get(int index) {
    if (index < 0 || index >= size) {
      throw new ArrayIndexOutOfBoundsException(index);
    }
    return theData[index];
  }

  /** Set the value in the array based on its index.
        @param index - The index of the item desired
        @param newValue - The new value to store at this position
        @return The old value at this position
        @throws ArrayIndexOutOfBoundsException - if the index
        is negative or if it is greater than or equal to the
        current size
   */
  public E set(int index, E newValue) {
    if (index < 0 || index >= size) {
      throw new ArrayIndexOutOfBoundsException(index);
    }
    E oldValue = theData[index];
    theData[index] = newValue;
    return oldValue;
  }

  /** Remove an entry based on its index
        @param index - The index of the entry to be removed
        @return The value removed
        @throws ArrayIndexOutOfBoundsException - if the index
        is negative or if it is greater than or equal to the
        current size
   */
  public E remove(int index) {
    if (index < 0 || index >= size) {
      throw new ArrayIndexOutOfBoundsException(index);
    }
    E returnValue = theData[index];
    for (int i = index + 1; i < size; i++) {
      theData[i - 1] = theData[i];
    }
    size--;
    return returnValue;
  }

  /** Allocate a new array to hold the directory
   */
  private void reallocate() {
    capacity = 2 * capacity;
    E[] newData = (E[])new Object[capacity];
    System.arraycopy(theData, 0, newData, 0, size);
    theData = newData;
  }

  /** Get the current size of the array
        @return The current size of the array
   */
  public int size() {
    return size;
  }
}

/**************************************************************
* I, Jeff Thomas, certify that each part of this program was
* written by me, except as noted within the code.
*
*						_________________________
***************************************************************/